package org.ricks.ioc;

import org.ricks.ioc.anno.*;
import org.ricks.ioc.definition.*;
import org.ricks.ioc.event.EventBus;
import org.ricks.ioc.event.RicksContextStartedIEvent;
import org.ricks.ioc.event.RicksContextStoppedIEvent;
import org.ricks.ioc.utils.AnnotationUtils;
import org.ricks.ioc.utils.ClassScanner;
import org.ricks.ioc.utils.Logger;
import org.ricks.ioc.utils.SystemClock;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author ricks
 * @date 2023/1/1114:25
 */
public class RicksContext {

    private RicksContext() {
        classes = ClassScanner.scanPackage("org.ricks");
    }

    public static RicksContext me() {
        return Holder.ME;
    }

    /** 通过 JVM 的类加载机制, 保证只加载一次 (singleton) */
    private static class Holder {
        static final RicksContext ME = new RicksContext();
    }

    private final Map<Class<?>, DefaultBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(1024);
    private final Map<Class<? extends Annotation>, List<LifeCycleMethod>> lifeCycleMethodMap = new HashMap<>();
    private final List<BeanAnalysisProcessor> beanAnalysisProcessors = new ArrayList<>();

    private final Set<Class<?>> classes;

    public void init() {
        SystemClock.INSTANCE.initialize(); //初始化时间tick机制
        classes.forEach(this::analysisClass); //解析class,实例化
        finishBeanInitialization(beanDefinitionMap.values());

        // 4/
        beanAnalysisProcessors.forEach(beanAnalysisProcessor -> {
            beanDefinitionMap.values().forEach(defaultBeanDefinition -> beanAnalysisProcessor.postProcessAfterInitialization(defaultBeanDefinition.getBean()));
        });

        // 3、初始化方法...
        invokeCustomAnnotationMethod(Init.class); //初始化Init

        EventBus.post(new RicksContextStartedIEvent());//发布容器初始化事件
    }

    public void beanAnalysisProcessor () {
        beanAnalysisProcessors.forEach(beanAnalysisProcessor -> {
            beanDefinitionMap.values().forEach(defaultBeanDefinition -> beanAnalysisProcessor.postProcessAfterInitialization(defaultBeanDefinition.getBean()));
        });
    }

    public void beanAnalysisProcessor (Object bean) {
        beanAnalysisProcessors.forEach(beanAnalysisProcessor -> beanAnalysisProcessor.postProcessAfterInitialization(bean));
    }

    public <T> T getInstance(Class<T> clazz) {
        Object bean = beanDefinitionMap.containsKey(clazz) ? beanDefinitionMap.get(clazz).getBean() : null;
        return clazz.isInstance(bean) ? clazz.cast(bean) : null; // 通过 Class.cast() 安全转换
    }

    public void addLifeCycleMethod (Class<? extends Annotation> klass, LifeCycleMethod lifeCycleMethod) {
        List<LifeCycleMethod> lifeCycleMethods = lifeCycleMethodMap.computeIfAbsent(klass, k -> new ArrayList<>());
        lifeCycleMethods.add(lifeCycleMethod);
    }

    /**
     * bean 解析器
     * @param beanAnalysisProcessor
     */
    public void addBeanAnalysisProcessor (BeanAnalysisProcessor beanAnalysisProcessor) {
        beanAnalysisProcessors.add(beanAnalysisProcessor);
    }

    public <T> List<T> getBeans(Class<T> clazz) {
        Object o = beanDefinitionMap.get(clazz).getBean();
        if (o instanceof List<?> rawList) {
            return rawList.stream()
                    .filter(clazz::isInstance)
                    .map(clazz::cast)
                    .collect(Collectors.toList());
        }
        return List.of();
    }


    public List<Object> allBeans() {
        return beanDefinitionMap.values().stream()
                .map(DefaultBeanDefinition::getBean)
                .collect(Collectors.toList());
    }



    /**
     * 分析Class
     *
     * @param klass Class
     */
    public void analysisClass(Class<?> klass) {
        // 接口、内部类、枚举、注解和匿名类 直接忽略
        if (klass.isInterface() || klass.isMemberClass() || klass.isEnum() || klass.isAnnotation() || klass.isAnonymousClass()) {
            return;
        }

        // 抽象类和非Public的也忽略
        int modify = klass.getModifiers();
        if (Modifier.isAbstract(modify) || (!Modifier.isPublic(modify))) {
            return;
        }

        // 目标类上实际注解类型    实现ApplicationListener 自动注入IOC
        if (klass.isAnnotationPresent(Configuration.class)) {
            analyticalConfiguration(klass);
            return;
        }

        Annotation annotation = AnnotationUtils.getAnnotation(klass, Bean.class);

        // 查找带有@Bean注解或其他注解上有@Bean注解的类
        if(Objects.nonNull(annotation) || BeanAnalysisProcessor.class.isAssignableFrom(klass)) analytical(klass); //只要是Bean

    }

    /**
     * 协议入口控制类(模块化)
     */
    public DefaultBeanDefinition analytical(Class<?> klass) {
        DefaultBeanDefinition definition = new DefaultBeanDefinition(klass);
        // 注册实现类本身
        beanDefinitionMap.put(klass, definition);
        // 注册所有实现的接口
        for (Class<?> interfaceClass : klass.getInterfaces()) {
            beanDefinitionMap.put(interfaceClass, definition);
        }
        return definition;
    }

    public DefaultBeanDefinition analytical(Object obj) {
        DefaultBeanDefinition definition = new DefaultBeanDefinition(obj);
        // 注册实现类本身
        beanDefinitionMap.put(obj.getClass(), definition);
        // 注册所有实现的接口
        for (Class<?> interfaceClass : obj.getClass().getInterfaces()) {
            beanDefinitionMap.put(interfaceClass, definition);
        }
        return definition;
    }


    public void analyticalConfiguration(Class<?> klass) {
        DefaultBeanDefinition definition = new ConfigurationBeanDefinition(klass);
        beanDefinitionMap.put(klass, definition);
    }


    /**
     * 初始化和依赖注入的关系
     */
    public void finishBeanInitialization(Collection<? extends BeanDefinition> beans) {
        beans.forEach(BeanDefinition::injection);
    }

    private void invokeCustomAnnotationMethod (Class<? extends Annotation> klass) {
        List<LifeCycleMethod> lifeCycleMethods = lifeCycleMethodMap.getOrDefault(klass, List.of());
        lifeCycleMethods.stream().sorted(Comparator.comparingInt(LifeCycleMethod::priority)).forEach(LifeCycleMethod::invoke);
    }

    public void stop() {
        // 3、初始化方法...
        invokeCustomAnnotationMethod(PreDestroy.class); //销毁
        EventBus.post(new RicksContextStoppedIEvent()); //容器销毁事件
        //销毁时间tick机制
        SystemClock.INSTANCE.destroy();
    }


    public void refreshBean(Class<?> targetClass) {
        // 从RicksContext中获取旧实例，并替换为新实例
        try {
            DefaultBeanDefinition definition = analytical(targetClass);
            definition.injection(); // 重新注入依赖
            RicksContext.me().beanAnalysisProcessor(definition.getBean());
        } catch (Exception e) {
            Logger.error("刷新Bean失败", e);
        }
    }


    /**
     * 扫描包，不同模块使用 IOC ORM PROTOCO
     * @param scanBasePackages
     */
    public Set<Class<?>> scan(Set<String> scanBasePackages) {
        Set<Class<?>> scanPackages = new HashSet<>();
        scanBasePackages.forEach(packageName -> scanPackages.addAll(ClassScanner.scanPackage(packageName)));
        Logger.debug("包名"+Arrays.toString(scanBasePackages.toArray()) + " 扫描成功，共扫描class[" + scanPackages.size() + "]");
        classes.addAll(scanPackages);
        return scanPackages;
    }

    public Set<Class<?>> projectClasses() {
        return classes;
    }


    /**
     * 热更类 - 使用类加载器隔离策略
     * @param classBytes 新的类字节码
     * @return 热更结果
     */
    public String hotfixClass(byte[] classBytes) {
        HotfixManager.getLock().lock();
        try {
            String className = HotfixManager.parseClassName(classBytes);
            Logger.info("准备执行热更 className:{}", className);

            // 使用类加载器隔离策略热更
            Class<?> newClass = HotfixManager.hotfixClass(classBytes);

            // 重新初始化Bean（需要刷新RicksContext中的实例）
            refreshBean(newClass);

            return "OK";
        } catch (Exception e) {
            Logger.error("热更失败", e);
            return "热更失败: " + e.getMessage();
        } finally {
            HotfixManager.getLock().unlock();
        }
    }


}
